package com.example.demo.yanglq.config;

import com.example.demo.yanglq.component.jedis.RedisClient;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

/**
 * 单机redis 配置
 * Created by blj on 2017/12/8.
 */
@Configuration
public class RedisConfig {

    @Value("${spring.redis.sentinel.nodes}")
    private String nodeCluters;

    @Value("${spring.redis.host}")
    private String hostName;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.sentinel}")
    private boolean isSentinel;

    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;
    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;
    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;
//    @Value("${spring.redis.timeout}")
//    private int timeout;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private int maxWaitMillis;
    @Value("${spring.redis.database}")
    private int database;
    @Value("${spring.redis.sentinel.master}")
    private String master;

    /******************** 配置redis--Start   *******************/
    @Bean(name = "jedisPoolConfig")
    JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig pool = new JedisPoolConfig();
        pool.setMaxIdle(maxIdle);
        pool.setMinIdle(minIdle);
        pool.setMaxTotal(maxActive);
        pool.setMaxWaitMillis(maxWaitMillis);
        return pool;
    }

    @Bean(name = "redisSentinelConfiguration")
    public RedisSentinelConfiguration getRedisSentinelConfiguration() {
        RedisSentinelConfiguration configuration = new RedisSentinelConfiguration();
        Set<RedisNode> nodes = new HashSet<>();

        String[] nodec = nodeCluters.split(",");
        for (int i = 0; i < nodec.length; i++) {
            String hostName = nodec[i].split(":")[0];
            int port = Integer.parseInt(nodec[i].split(":")[1]);
            RedisNode node = new RedisNode(hostName, port);
            nodes.add(node);
        }

        configuration.setSentinels(nodes);
        configuration.setMaster(master);
//        configuration.setMaxRedirects(maxRedirects);
        return configuration;
    }

    @Bean(name = "jedisConnectionFactory")
    JedisConnectionFactory jedisConnectionFactory(
            @Qualifier("redisSentinelConfiguration") RedisSentinelConfiguration clusterConfig,
            @Qualifier("jedisPoolConfig") JedisPoolConfig jedisPoolConfig) {
        JedisConnectionFactory jedisConnectionFactory;

        //单机模式
        if (!isSentinel) {
            jedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig);
            jedisConnectionFactory.setHostName(hostName);
            jedisConnectionFactory.setPort(port);
            jedisConnectionFactory.setPassword(password);
            jedisConnectionFactory.setDatabase(database);
        } else {
            //哨兵模式
            jedisConnectionFactory = new JedisConnectionFactory(clusterConfig, jedisPoolConfig);
            jedisConnectionFactory.setPassword(password);
            return jedisConnectionFactory;

        }
//        //	判断密码是否存在，存在设置值
//        checkPasswordIfNull(jedisConnectionFactory);
        return jedisConnectionFactory;
    }

    @Bean(name = "jedisPool")
    @Autowired
    public JedisPool jedisPool(@Qualifier("jedisPoolConfig") JedisPoolConfig config,
                               @Value("${spring.redis.host}") String host,
                               @Value("${spring.redis.port}") int port,
                               @Value("${spring.redis.password}") String password,
                               @Value("${spring.redis.timeout}") int timeout,
                               @Value("${spring.redis.database}") int database) {
//        if (StringUtils.isBlank(password)) {
//            password = null;
//        }
        return new JedisPool(config, host, port, timeout, password, database);
    }


    /**
     * 可以选择用redisTemplate来操作redis
     * RedisTemplate配置
     */
    @Bean(name = "redisTemplate")

    public RedisTemplate<String, Object> getRedisTemplate(
            @Qualifier("jedisConnectionFactory") JedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setConnectionFactory(factory);
        // 使用Jackson2JsonRedisSerialize 替换默认序列化
        @SuppressWarnings({"rawtypes", "unchecked"})
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        // 设置value的序列化规则和 key的序列化规则
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setKeySerializer(new StringRedisSerializer());

        redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setEnableDefaultSerializer(true);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean(name = "RedisClient")
    @Autowired
    public RedisClient redisClient(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
        RedisClient redisClient = new RedisClient();
        redisClient.setRedisTemplate(redisTemplate);
        return redisClient;
    }


}
